package com.bilibili.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.bilibili.dao.UserInfoMapper;
import com.bilibili.dao.UserMapper;
import com.bilibili.domain.PageResult;
import com.bilibili.domain.constant.UserConstant;
import com.bilibili.domain.entity.RefreshToken;
import com.bilibili.domain.entity.User;
import com.bilibili.domain.entity.UserInfo;
import com.bilibili.domain.exception.ConditionException;
import com.bilibili.service.ElasticSearchService;
import com.bilibili.service.RefreshTokenService;
import com.bilibili.service.UserAuthService;
import com.bilibili.service.UserService;
import com.bilibili.utils.MD5Util;
import com.bilibili.utils.RSAUtil;
import com.bilibili.utils.TokenUtil;
import com.mysql.cj.util.StringUtils;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author www
* @description 针对表【t_user(用户表)】的数据库操作Service实现
* @createDate 2024-06-02 19:58:42
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private UserAuthService userAuthService;
    @Resource
    private ElasticSearchService elasticSearchService;

    @Resource
    private RefreshTokenService refreshTokenService;

    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    LambdaQueryWrapper<UserInfo> infoWrapper = new LambdaQueryWrapper<>();
    @Override
    public void addUser(User user) {
        String phone = user.getPhone();
        if (StringUtils.isNullOrEmpty(phone)){
            throw new ConditionException("手机号不能为空");
        }
        User userByPhone = getUserByPhone(phone);
        if (userByPhone!=null){
            throw new ConditionException("该手机号已被注册");
        }
        Date now = new Date();//作为盐值用于md5加密
        String password = user.getPassword();//经过前端加密
        String salt = String.valueOf(now.getTime());
        String originPassword;//原始密码
        try {
            originPassword=RSAUtil.decrypt(password);
        } catch (Exception e) {
            throw new ConditionException("密码解密失败!");
        }
        String md5Password = MD5Util.sign(originPassword, salt, "UTF-8");
        user.setSalt(salt);
        user.setPassword(md5Password);
        user.setCreateTime(now);
        user.setUpdateTime(now);
        int insert = userMapper.insert(user);

        //添加用户信息
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(user.getId());
        userInfo.setNick(UserConstant.DEFAULT_NIK);
        userInfo.setBirth(UserConstant.DEFAULT_BIRTH);
        userInfo.setGender(UserConstant.GENDER_UN_KNOW);
        userInfo.setCreateTime(now);
        userInfo.setUpdateTime(now);
        userInfoMapper.insert(userInfo);
        elasticSearchService.addUserInfo(userInfo);

        //添加用户默认角色
        userAuthService.addUserDefaultRole(user.getId());
    }

    @Override
    public String login(User user) throws Exception{
        String phone = user.getPhone();
        if (StringUtils.isNullOrEmpty(phone)){
            throw new ConditionException("手机号不能为空");
        }
        User dbUser = this.getUserByPhone(phone);
        if (dbUser==null){
            throw new ConditionException("当前用户不存在");
        }
        String password = user.getPassword();
        String salt = dbUser.getSalt();
        String originPassword;//原始密码
        try {
            originPassword=RSAUtil.decrypt(password);
        } catch (Exception e) {
            throw new ConditionException("密码解密失败!");
        }
        String md5Password = MD5Util.sign(originPassword, salt, "UTF-8");
        if (!md5Password.equals(dbUser.getPassword())){
            throw new ConditionException("密码错误");
        }

        return TokenUtil.generateToken(dbUser.getId());
    }

    @Override
    public PageResult<UserInfo> pageListUserInfos(JSONObject params) {
        Integer num = params.getInteger("num");
        Integer size = params.getInteger("size");
        String nick = params.getString("nick");
        IPage<UserInfo> page = new Page<>(size,num);

        infoWrapper.like(UserInfo::getNick,nick).orderByDesc(UserInfo::getUserId);
        userInfoMapper.selectPage(page,infoWrapper);

        long total = page.getTotal();
        List<UserInfo> records = page.getRecords();
        return new PageResult<>(total,records);
    }

    @Override
    public Map<String, Object> loginForDts(User user) throws Exception {
        String phone = user.getPhone();
        if (StringUtils.isNullOrEmpty(phone)){
            throw new ConditionException("手机号不能为空");
        }
        User dbUser = this.getUserByPhone(phone);
        if (dbUser==null){
            throw new ConditionException("当前用户不存在");
        }
        String password = user.getPassword();
        String salt = dbUser.getSalt();
        String originPassword;//原始密码
        try {
            originPassword=RSAUtil.decrypt(password);
        } catch (Exception e) {
            throw new ConditionException("密码解密失败!");
        }
        String md5Password = MD5Util.sign(originPassword, salt, "UTF-8");
        if (!md5Password.equals(dbUser.getPassword())){
            throw new ConditionException("密码错误");
        }

        Long userId = dbUser.getId();
        String accessToken = TokenUtil.generateToken(dbUser.getId());
        //刷新token
        String refreshToken = TokenUtil.generateRefreshToken(dbUser.getId());

        //保存refresh token到数据库
        refreshTokenService.deleteRefreshToken(refreshToken, userId);
        refreshTokenService.addRefreshToken(refreshToken, userId,new Date());

        Map<String,Object> map = new HashMap<>();
        map.put("accessToken",accessToken);
        map.put("refreshToken",refreshToken);

        return map;
    }

    @Override
    public void logout(String refreshToken, Long userId) {
        refreshTokenService.deleteRefreshToken(refreshToken, userId);
    }

    @Override
    public String refreshAccessToken(String refreshToken) throws Exception {
        RefreshToken refreshTokenDetail = refreshTokenService.getRefreshTokenDetail(refreshToken);
        if (refreshToken==null){
            throw new ConditionException("555","token过期! ");
        }
        //用户token过期而刷新token不过期，用户token会被刷新，防止用户在使用过程中下线
        Long userId = refreshTokenDetail.getUserId();
        return TokenUtil.generateToken(userId);
    }

    public User getUserByPhone(String phone){
        wrapper.eq(User::getPhone,phone);
        User user = userMapper.selectOne(wrapper);
        return user;
    }
}




